#pragma once

#include "Thread.h"
#include "IpcBuff.h"

#include <queue>

class CIpcClient
{
public:
	CIpcClient(void);
	~CIpcClient(void);

private:
	typedef   queue<CIpcBuff*>          CacheQueue;
	typedef function<void (long,char*,int)>		 RecvCallBack;
	typedef function<void (long,int)>            EventCallBack;

private:
	SOCKET								m_ClientSock;
	BOOL								m_bStart;
	BOOL								m_bEnableHeartBeat;
	BOOL								m_bConnectServer;
	sockaddr_in							m_ServerAddr;
	CThread								m_ConnectThread;
	CThread							    m_SendThread;
	CThread								m_RecvThread;
	CacheQueue							m_SendQueue;
	long								m_nHeartBeatTimeOutCount;
	RecvCallBack						m_lpfnRecvCallBack;
	EventCallBack						m_lpfnEventCallBack;
	unsigned int						m_nCurrentEvent;

public:
	int Start(int nPort);
	void Send(char* buff, int len);
	void EnableHeartBeat(bool bEnable);
	template<typename T> 
	void RegsitRecvCallBack(T* obj,void (T::* lpmemberfn)(long,char*,int ) )
	{
		m_lpfnRecvCallBack = tr1::bind(lpmemberfn,obj,_1,_2,_3);    
	}

	template<typename T> 
	void RegsitEventCallBack(T* obj,void (T::* lpmemberfn)(long,int ) )
	{
		m_lpfnEventCallBack = tr1::bind(lpmemberfn,obj,_1,_2);    
	}

protected:
	void ConnectThread(LPVOID lpParam);
	void SendThread(LPVOID lpParam);
	void RecvThread(LPVOID lpParam);
	void Disconnect(void);
	void RemoveSendQueue();
	int  Send(SOCKET sock,char* buf,int lenth,int flag = 0);
	int  Recv(SOCKET sock,char* buf,int lenth,int flag = 0);
	void DispatchEvent(long lHandle, int nEvent);
};
